package com.zny.sescore.rule;

import com.zny.sescore.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import javax.script.*;
import java.math.BigDecimal;
import java.util.Map;

/**
 * @version: V1.0
 * @author: zhangnayi
 * @className: RuleEngineManager
 * @packageName: com.palmdoctor.mb.base.rule
 * @description: 规则引擎
 * @data: 2021-08-09 10:08
 **/
@Slf4j
public class RuleEngineManager {

    private ScriptEngine engine;

    private Bindings bindings = new SimpleBindings();

    private String extendScript = "";

    private String ruleScript;

    public static RuleEngineManager instance() {
        RuleEngineManager instance = new RuleEngineManager();
        ScriptEngineManager manager = new ScriptEngineManager();
        instance.engine = manager.getEngineByName("JavaScript");
        instance.extendScript();
        return instance;
    }


    public RuleEngineManager addParam(String key, Object value) {
        bindings.put(key, value);
        return this;
    }

    public RuleEngineManager addParam(Map<String, Object> map) {
        bindings.putAll(map);
        return this;
    }

    public RuleEngineManager setRuleScript(String ruleScript) {
        this.ruleScript = ruleScript;
        return this;
    }

    @SuppressWarnings("unchecked")
    public <T> T eval() {
        try {
            String evalScript = extendScript + ";" + ruleScript;
            log.debug("RuleEngineManager eval script={}, bindings={}", ruleScript, JsonUtil.objectToString(bindings));
            return (T) engine.eval(evalScript, bindings);
        } catch (ScriptException e) {
            log.error("", e);
            return null;
        }
    }

    public BigDecimal eval2() {
        return new BigDecimal(eval().toString());
    }

    public boolean match() {
        try {
            String evalScript = extendScript + ";" + ruleScript;
            log.debug("RuleEngineManager eval script={}, bindings={}", ruleScript, JsonUtil.objectToString(bindings));
            return (Boolean) engine.eval(evalScript, bindings);
        } catch (ScriptException e) {
            log.error("", e);
            return false;
        }
    }

    private RuleEngineManager extendScript() {
        this.extendScript = ScriptConstant.INCLUDE + ";" + ScriptConstant.EXCLUDE;
        log.debug("RuleEngineManager extend script = {}", this.extendScript);
        return this;
    }

    public static void main(String[] args) throws ScriptException {

        String s = "0.0391*a+0.7917*b+1.3388*c ";
        Object result1 = RuleEngineManager.instance()
                .addParam("a", new BigDecimal(1))
                .addParam("b", new BigDecimal(2))
                .addParam("c", new BigDecimal(3))
                .setRuleScript(s)
                .eval();
        System.out.println(new BigDecimal(result1.toString()));
        Object result2 = RuleEngineManager.instance()
                .addParam("a", 1)
                .setRuleScript("function contain(a){ return a.indexOf('a')} contain('aaa')")
                .eval();
        System.out.println(result2);

        Object result3 = RuleEngineManager.instance()
                .addParam("a", "0")
                .addParam("b", "a")
                .setRuleScript("a === '0'")
                .eval();
        System.out.println(result3);
    }
}